package com.ryenlii.datatrans.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eyelake.iot.common.domain.constants.IotCommonConstants;
import com.eyelake.iot.common.domain.dto.tsdb.IotStorageDataDto;
import com.ryenlii.datatrans.core.config.TdengineDbConfiguration;
import com.ryenlii.datatrans.core.constant.StbConstants;
import com.ryenlii.datatrans.entity.OperationTrack;
import com.ryenlii.datatrans.service.ITdengineService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


@Slf4j
@Service("operationTrackDb")
public class OperationTrackDbServiceImpl implements ITdengineService<OperationTrack> {

    @Resource
    private TdengineDbConfiguration tdengineDbConfig;

    @Override
    public boolean getSwitchF() {
        return tdengineDbConfig.getSwitchF();
    }

    @Override
    public int saveToDb(OperationTrack track) {
        long current = DateUtil.current();
        IotStorageDataDto iotData = new IotStorageDataDto();
        iotData.setTableName(StbConstants.STB_OPERATION_TRACK);
        iotData.setUploadTime(current);
        Map<String, String> tagMap = new LinkedHashMap<>();
        tagMap.put(StbConstants.DEVICE_NUMBER, track.getDeviceNumber());
        iotData.setTagMap(tagMap);

        Map<String, Object> field = new LinkedHashMap<>();
        field.put(StbConstants.ID, track.getId());
        field.put(StbConstants.LONGITUDE, track.getLongitude());
        field.put(StbConstants.LATITUDE, track.getLatitude());
        field.put(StbConstants.REPORT_TIME, current);
        iotData.setFieldMap(field);

        return tdengineDbConfig.insertUsingTemplate(StbConstants.STB_OPERATION_TRACK,
                StbConstants.OPERA_TRACK + iotData.getTagMap().get(StbConstants.DEVICE_NUMBER),
                iotData.getFieldMap(),
                iotData.getTagMap(),
                iotData.getUploadTime());
    }

    @Override
    public List selectBySql(String querySql) {
        List<Map<String, Object>> maps = tdengineDbConfig.executeQuery(querySql);
        return maps;
    }

    @Override
    public List<OperationTrack> select(String querySql) {
        List<OperationTrack> list = tdengineDbConfig.getList(querySql, OperationTrack.class);
        return list;
    }

    @Override
    public List<OperationTrack> select(Map<String, Object> queryMap) {
        StringBuilder querySql = new StringBuilder();
        String devNo = MapUtil.getStr(queryMap, StbConstants.DEVICE_NUMBER);
        querySql.append("select ")
                .append("time, ")
                .append(StbConstants.REPORT_TIME)
                .append(", ")
                .append(StbConstants.LONGITUDE)
                .append(", ")
                .append(StbConstants.LATITUDE)
                .append(" from ");
        // 表名
        if (StrUtil.isNotBlank(devNo)) {
            querySql.append(StbConstants.OPERA_TRACK).append(devNo);
        } else {
            querySql.append(StbConstants.STB_OPERATION_TRACK);
        }
        long startTime;
        long endTime;
        String startTimeStr = MapUtil.getStr(queryMap, "startTime");
        String endTimeStr = MapUtil.getStr(queryMap, "endTime");
        // 不传时间默认7天
        if (Objects.isNull(startTimeStr) && Objects.isNull(endTimeStr)) {
            startTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now().plusDays(7));
            endTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now());
        } else {
            startTime = LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss"));
            endTime = LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss"));
        }
        // 查询条件
        querySql.append(" where ")
                .append(StbConstants.DEVICE_NUMBER)
                .append("= '")
                .append(devNo)
                .append("'");
        querySql.append(" and reporttime >=")
                .append(timeToString(startTime))
                .append(" and reporttime <=")
                .append(timeToString(endTime));
        querySql.append(" order by reporttime desc");
        List<OperationTrack> list = tdengineDbConfig.getList(querySql.toString(), OperationTrack.class);

        return list;
    }

    @Override
    public Long selectCountFromTdBySql(String sql) {
        return tdengineDbConfig.executeCountQuery(sql);
    }

    @Override
    public Page<OperationTrack> queryHistoryData(Integer pageSize, Integer currentPage, Map<String, Object> queryMap, Map<String, String> map) {
        int offset = (currentPage - 1) * pageSize;
        Page<OperationTrack> page = new Page<>(currentPage, pageSize);

        StringBuffer countSql = queryHistoryDataTableSql2(queryMap, Boolean.TRUE);
        // 查询数量
        Long count = selectCountFromTdBySql(countSql.toString());
        // 定义查询sql
        StringBuffer querySql = queryHistoryDataTableSql2(queryMap, Boolean.FALSE);
        querySql.append(StrUtil.format(IotCommonConstants.INFLUXDB_PAGE, pageSize, offset));
        // 查询结果
        List<OperationTrack> historyListDtoList = select(querySql.toString());
        page.setRecords((historyListDtoList));
        page.setTotal(count);
        return page;
    }

    public StringBuffer queryHistoryDataTableSql2(Map<String, Object> historyDataTableMap, Boolean countFlag) {
        StringBuffer querySql = new StringBuffer();
        String devNo = MapUtil.getStr(historyDataTableMap, StbConstants.DEVICE_NUMBER);
        if (countFlag) {
            querySql.append("select count(")
                    .append(StbConstants.REPORT_TIME)
                    .append(") from ");
        } else {
            querySql.append("select ")
                    .append("time, ")
                    .append(StbConstants.REPORT_TIME).append(", ")
                    .append(StbConstants.LONGITUDE).append(", ")
                    .append(StbConstants.LATITUDE)
                    .append("from ");
        }
        // 表名
        if (StrUtil.isNotBlank(devNo)) {
            querySql.append(StbConstants.OPERA_TRACK).append(devNo);
        } else {
            querySql.append(StbConstants.STB_OPERATION_TRACK);
        }
        // 查询条件
        querySql.append(" where 1=1 ").append(getWhere(historyDataTableMap));
        if (!countFlag) {
            querySql.append(" order by time desc");
        }
        return querySql;
    }

    private String getWhere(Map<String, Object> qurMap) {
        StringBuilder where = new StringBuilder();
        qurMap.forEach((s, o) -> where.append(" and ").append(s).append(" = '").append(o).append("'"));
        return where.toString();
    }

    @Override
    public StringBuffer queryHistoryDataTableSql(Map<String, Object> historyDataTableMap, Boolean countFlag) {
        StringBuffer querySql = new StringBuffer();
        long startTime;
        long endTime;
        String startTimeStr = MapUtil.getStr(historyDataTableMap, "startTime");
        String endTimeStr = MapUtil.getStr(historyDataTableMap, "endTime");
        // 不传时间默认7天
        if (Objects.isNull(startTimeStr) && Objects.isNull(endTimeStr)) {
            startTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now().plusDays(7));
            endTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now());
        } else {
            startTime = LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss"));
            endTime = LocalDateTimeUtil.toEpochMilli(LocalDateTimeUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss"));
        }
        String devNo = MapUtil.getStr(historyDataTableMap, StbConstants.DEVICE_NUMBER);
        if (countFlag) {
            querySql.append("select count(")
                    .append(StbConstants.ID)
                    .append(") from ");
        } else {
            querySql.append("select ")
                    .append("time, ")
                    .append(StbConstants.ID).append(", ")
                    .append(StbConstants.REPORT_TIME).append(", ")
                    .append(StbConstants.LONGITUDE).append(", ")
                    .append(StbConstants.LATITUDE)
                    .append("from ");
        }
        // 表名
        if (StrUtil.isNotBlank(devNo)) {
            querySql.append(StbConstants.OPERA_TRACK).append(devNo);
        } else {
            querySql.append(StbConstants.STB_OPERATION_TRACK);
        }
        // 查询条件
        querySql.append(" where ")
                .append(StbConstants.DEVICE_NUMBER)
                .append("= '")
                .append(devNo)
                .append("'");
        querySql.append(" and time >=")
                .append(timeToString(startTime))
                .append(" and time <=")
                .append(timeToString(endTime));
        if (!countFlag) {
            querySql.append(" order by time desc");
        }
        return querySql;
    }


}
